﻿using System;
using NUnit.Framework;
using Rhino.Mocks;
using CI;
using CI.Interfaces;
using CI.Organism;

namespace Mesopotamia.UnitTests.Organism
{

    [TestFixture]
    public class iRobotBindingTests
    {

        private SynapseIODelegate _leftBumperHandler = null;
        private SynapseIODelegate _rightBumperHandler = null;
        private SynapseIODelegate _cameraHandler = null;
        private ISynapse _synapse;
        private SynapseIO _synapseIO;
        private IHostingEnvironment _hostingEnvironment;
        private INeuralSystem _neuralSystem;
        private IOrganism _organism;
        private iRobot _irobot;
        private bool _eventFired;
        private Action<Int64> moveForward;
        private Action<Int64> turnLeft;
        private Action<Int64> turnRight;


        [SetUp]
        public void Setup()
        {

            _hostingEnvironment = MockRepository.GenerateStub<IHostingEnvironment>();
            _hostingEnvironment.Organisms = MockRepository.GenerateStub<IOrganismCollection>();
            _organism = MockRepository.GenerateStub<IOrganism>();
            ICellCollection cells = new CellCollection();
            _organism.Cells = cells;
            _irobot = new iRobot(_organism, Guid.NewGuid());
            _neuralSystem = MockRepository.GenerateStub<INeuralSystem>();
            _neuralSystem.Organism = _organism;
            _synapse = new SimpleSynapse(Guid.NewGuid(), _neuralSystem);
            _leftBumperHandler = null;
            _rightBumperHandler = null;
            _eventFired = false;
            moveForward = new Action<long>(MovementAction);
            turnLeft = new Action<long>(MovementAction);
            turnRight = new Action<long>(MovementAction);

            _organism.Stub(x => x.GetIOManifest()).Return(_irobot.IOManifest);

        }


        private void CreateSynapseAndBind(string bindingName)
        {
            _synapseIO = new SynapseIO(bindingName, "shortname", "desc", Guid.NewGuid());
            iRobot.BindSynapseIO(_organism, ref _leftBumperHandler, ref _rightBumperHandler,ref _cameraHandler, ref moveForward, ref turnLeft, ref turnRight);
        }

        [Test]
        public void BindSynapseIO_LeftBumper_NotNull()
        {

            Assert.IsNull(_leftBumperHandler);
            CreateSynapseAndBind(Globals.IROBOTLEFTFRONTBUMPER);
            Assert.IsNotNull(_leftBumperHandler);
        }

        [Test]
        public void BindSynapseIO_RightBumper_NotNull()
        {
            Assert.IsNull(_rightBumperHandler);
            CreateSynapseAndBind(Globals.IROBOTRIGHTFRONTBUMPER);
            Assert.IsNotNull(_rightBumperHandler);
        }

        private void CheckAndSetSyanpseIO(string synapseIO)
        {
            _synapse.AddSynapticConnectionTarget(_irobot.GetSynapseIO(synapseIO));
            _synapse.FireInput(100);
            Assert.IsFalse(_eventFired);
            CreateSynapseAndBind(synapseIO);
            _synapse.FireInput(100);
            Assert.IsTrue(_eventFired);
        }

        [Test]
        public void BindSynapseIO_IROBOTTURNLEFT_Fired()
        {
            CheckAndSetSyanpseIO(Globals.IROBOTTURNLEFT);
        }

        [Test]
        public void BindSynapseIO_IROBOTTURNRIGHT_Fired()
        {
            CheckAndSetSyanpseIO(Globals.IROBOTTURNRIGHT);
        }

        [Test]
        public void BindSynapseIO_IROBOTFORWARD_Fired()
        {
            CheckAndSetSyanpseIO(Globals.IROBOTFORWARD);
        }

        public void MovementAction(Int64 iputValue)
        { _eventFired = true; }
    }
}
